/****
	Copyright 2012 Taras Kulbachka

	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

		http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/

package com.atdevsoft.apps.abyss;

import org.htmlparser.filters.NodeClassFilter;
import org.htmlparser.nodes.TagNode;
import org.htmlparser.util.NodeList;

import com.atdevsoft.apps.abyss.AbstractQuoteDownloader.OnPageProcessedListener;

import android.app.IntentService;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.PowerManager;

public class AbyssDownloaderService extends IntentService {
    
	private class BashQuoteDownloader extends AbstractQuoteDownloader {
		private static final String BASE_ADDRESS = "http://bash.im";
		private static final String STARTING_ADDRESS = "http://bash.im/abyssbest";
		
		private static final int SKIP_BEFORE_DIE = 3;
		private static final int GAP_TO_FALLBACK = 10;				
		
		private int mLastDlQuote;
		private int mTargetNodeOnPage;	
		private NodeClassFilter mNodeFilter;
		
		public BashQuoteDownloader(String tableName) {
			super(tableName);
		}
	    
	    @Override
	    protected int getNearestSavedQuote(int quoteId) {
			int res = 0;
	        Cursor getQuote = DatabaseHelper.rawQuery("select " + DatabaseHelper.QUOTES_SOURCE_ID + 
	        		" from " + DatabaseHelper.TABLE_NAME_ABYSSBESTQUOTES + 
	        		" where " +	DatabaseHelper.QUOTES_SOURCE_ID + " >= " + String.valueOf(quoteId) +
	        		" order by 1 asc limit 0, 1", null);
	        if (getQuote.getCount() == 1) {
	        	getQuote.moveToFirst();
	        	res = getQuote.getInt(0);
	        }
	        getQuote.close();
	        return res;			
		}				

	    @Override
		protected String getPageAddress(String nextPageRef) {
			if (nextPageRef == null)
				return STARTING_ADDRESS;
			else
				return BASE_ADDRESS + nextPageRef;
		}
		
		@Override
		protected int processTag(TagNode tag, ContentValues output, boolean fastDownload) {
            
            try {
	            if ("current".equals(tag.getAttribute("class")) && "span".equals(tag.getRawTagName())) {
	            	NextSitePageRef = ((TagNode)tag.getNextSibling()).getAttribute("href");
	            	QuotesSitePageName = ((TagNode)tag.getChildren().elementAt(0)).getAttribute("value");
	            	//if ((txt != null) && checkIfNumber(txt))
	            	//	QuotesSitePageNumber = Integer.parseInt(txt);
	            	return STATUS_OK;		
	       		}
            } catch (Exception e) {
	        	return STATUS_ABORT;
	        }
       		
            if ("quote".equals(tag.getAttribute("class"))) {
            	mTargetNodeOnPage++;          
            	            	
            	NodeList children = tag.getChildren().extractAllNodesThatMatch(mNodeFilter); 
            	// children.size() == 2 -- otherwise it is ad block
            	// mTargetNodeOnPage > 1 -- first target node on bash is search box
            	if ((children.size() == 2) && (children.elementAt(0).getChildren().size() > 4) && (mTargetNodeOnPage > 1)) {  
            		NodeList headerNodes = children.elementAt(0).getChildren();
            		mLastDlQuote = Integer.parseInt(headerNodes.elementAt(3).getChildren().elementAt(0).getText().trim().substring(4));
            		
            		int nearestQuote = 0;
            		if (!fastDownload)
            			nearestQuote = getNearestSavedQuote(mLastDlQuote);
            		
            		if (nearestQuote == mLastDlQuote) {
            			if ((mTerminateOnDuplicates) && (PageSkippedQuotes >= SKIP_BEFORE_DIE)) { 
            				return STATUS_ABORT;
            			} else {
            				return STATUS_SKIP_QUOTE;            			
            			}
            		} else if (nearestQuote == 0 || (nearestQuote - mLastDlQuote < GAP_TO_FALLBACK)) {
            			output.put(DatabaseHelper.QUOTES_SOURCE_ID, mLastDlQuote); // quote source id
            			output.put(DatabaseHelper.QUOTES_POSTED, headerNodes.elementAt(1).getChildren().elementAt(0).getText().trim()); // quote posted at            		
            			output.put(DatabaseHelper.QUOTES_QUOTE, children.elementAt(1).toHtml()); // quote text	            		
            			return STATUS_OK;
            		} else {
            			return STATUS_FALLBACK_PAGE;            			
            		}	            		
            	}
            }
           	return STATUS_NEED_SUBPROCESS;			
		}

		@Override
		public int parsePage(String page, boolean terminateOnDuplicates, boolean fastDownload) {            
			mTargetNodeOnPage = 0;
			mNodeFilter = new NodeClassFilter(TagNode.class);
			return super.parsePage(page, terminateOnDuplicates, fastDownload);
		}
	}	

	// incoming 
    public static final String ACTION_DOWNLOAD_ABYSS_QUOTES = "com.atdevsoft.apps.abyss.DOWNLOAD_ABYSS_QUOTES";
    public static final String ACTION_PING_IS_DOWNLOADING = "com.atdevsoft.apps.abyss.PING_IS_DOWNLOADING";
    public static final String INTENT_EXTRA_PAGES_COUNT = "pages_count";
    public static final String INTENT_EXTRA_STOP_ON_DUPLICATE = "stop_on_duplicate";
    public static final String INTENT_EXTRA_FAST_DOWNLOAD = "fast_download";

	// outgoing     
	public static final String ACTION_DOWNLOAD_PAGE_DONE = "com.atdevsoft.apps.abyss.DOWNLOAD_PAGE_DONE";
	public static final String ACTION_DOWNLOAD_ALL_DONE = "com.atdevsoft.apps.abyss.DOWNLOAD_ALL_DONE";
	public static final String ACTION_PINGBACK_IDLE = "com.atdevsoft.apps.abyss.PINGBACK_IDLE";
	
	public static final String INTENT_EXTRA_PRECENT_DONE = "percent_done";
	public static final String INTENT_EXTRA_PAGE_NAME = "page_name";
	public static final String INTENT_EXTRA_RESULT_CODE = "result_code";
	public static final String INTENT_EXTRA_QUOTES_ADDED = "quotes_added";
	public static final String INTENT_EXTRA_QUOTES_SKIPPED = "quotes_skipped";
    
	
	private static final String LOCK_NAME_STATIC = "com.atdevsoft.apps.abyss";
	private static PowerManager.WakeLock lockStatic = null;
	
	private int mPageCounter;
	
    public AbyssDownloaderService(String name) {
        super(name);
    }

    public AbyssDownloaderService() {
        super("AbyssDownloaderService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        Context context = getApplicationContext();
        if (intent.getAction().equals(ACTION_PING_IS_DOWNLOADING)) {
        	Intent i = new Intent(ACTION_PINGBACK_IDLE);			
			sendBroadcast(i);	
        } else if (intent.getAction().equals(ACTION_DOWNLOAD_ABYSS_QUOTES)) {
        	final int pagesCount = intent.getExtras().getInt(INTENT_EXTRA_PAGES_COUNT);
        	
	        BashQuoteDownloader bqd = new BashQuoteDownloader(DatabaseHelper.TABLE_NAME_ABYSSBESTQUOTES);
	        mPageCounter = 0;
	        
	        bqd.setOnPageProcessedListener(new OnPageProcessedListener() {
				@Override
				public boolean onPageProcessed(final String pageName, final int quotesAdded, final int quotesSkipped) {
					Intent i = new Intent(ACTION_DOWNLOAD_PAGE_DONE);
					i.putExtra(INTENT_EXTRA_PAGE_NAME, pageName);
					i.putExtra(INTENT_EXTRA_QUOTES_ADDED, quotesAdded);
					i.putExtra(INTENT_EXTRA_QUOTES_SKIPPED, quotesSkipped);
					
					mPageCounter++;					
					i.putExtra(INTENT_EXTRA_PRECENT_DONE, (mPageCounter*100/pagesCount));
					sendBroadcast(i);					
					return true;
				}
				
				@Override
				public void onAllPagesProcessed(final int resultCode, final int totalQuotesAdded, final int totalQuotesSkipped) {
					lockStatic.release();					
					Intent i = new Intent(ACTION_DOWNLOAD_ALL_DONE);
					i.putExtra(INTENT_EXTRA_RESULT_CODE, resultCode);
					i.putExtra(INTENT_EXTRA_QUOTES_ADDED, totalQuotesAdded);
					i.putExtra(INTENT_EXTRA_QUOTES_SKIPPED, totalQuotesSkipped);
					sendBroadcast(i);
				}
			});	        
	         
	        boolean stopOnDuplicate = intent.getExtras().getBoolean(INTENT_EXTRA_STOP_ON_DUPLICATE, true);
	        boolean fastDownload = intent.getExtras().getBoolean(INTENT_EXTRA_FAST_DOWNLOAD, true);

	        PowerManager mgr = (PowerManager)context.getSystemService(Context.POWER_SERVICE);			
	        lockStatic = mgr.newWakeLock(PowerManager.FULL_WAKE_LOCK, LOCK_NAME_STATIC); 	        
	        lockStatic.acquire();
	        bqd.parsePages(pagesCount, stopOnDuplicate, fastDownload, true);        
	           
        }
    }
}
